{ "nbformat": 4, "nbformat_minor": 0, "metadata": { "colab": { "name": "game stats.ipynb", "provenance": [] }, "kernelspec": { "name": "python3", "display_name": "Python 3" }, "language_info": { "name": "python" }, "pycharm": { "stem_cell": { "cell_type": "raw", "source": [], "metadata": { "collapsed": false } } } }, "cells": [ { "cell_type": "markdown", "source": [ "# Game statistics\n", "\n", "## Try me\n","[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/ffraile/computer_science_tutorials/blob/main/source/Extra%20Exercises/Ex10.%20Game%20Statistics%20(solved).ipynb)[![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/ffraile/computer_science_tutorials/main?labpath=source%2FExtra%20Exercises%2FEx10.%20Game%20Statistics%20(solved).ipynb)\n", "\n", "## Problem definition\n", "You would like to build a program to collect statistics for a basketball game. The objective is to build a chatbot like assistant with the following logic and functionality: \n", "- Ask the user what is the name of the event\n", "- Ask the user the name of one of the teams\n", "- Ask the user for the name of the second team\n", "- Ask the user to confirm the start of the game\n", "- Once the name has started, ask the user if he wants to register a game statistic, either a fault or game points, or if he wants to stop the game: \n", " - if the user wants to register a fault, ask the user the number of the player and team that made the fault, and the number of the player that received the fault. Show a message with the total number of faults made by the player.\n", " - if the user wants to register points, ask the user for the player number and the team that score the points and if it´s a 1 point, 2 point or a 3 point shot. Show a message with the total number of points socred by the player. \n", "\n", "It is very important to register the date and time of every statistic, including the game start. To store this type of information, you can use the [datetime](https://docs.python.org/3/library/datetime.html) Python library, which provides convenient data types to deal with time and dates. Specifically, you can use: \n", "- ```datetime.datetime.now()```: This functions returns a datetime object with the current date and time. \n", "- ```isoformat()```: this datetime object method returns a string with the date and time in [ISO standard format](https://en.wikipedia.org/wiki/ISO_8601)\n", "\n", "Also, you may use a Python dictionaries to store the information of the statistics. This way, you can initialise the stats registry as an array: \n", "\n", "```python\n", "stats_array = []\n", "```\n", "\n", "And then, use the information provided by the user to build different dictionaries to store the information required for each type of statistic. The key *type* can be used to identify the type of statistic. The following code snippet contain examples for each type of statistic:\n", "\n", "```python\n", "# Game start\n", "{'type': 'game_start', 'timestamp': '2022-01-05T11:42:03.792167', 'teams': ['Valencia Basket', 'Real Madrid']}\n", "\n", "# Shot\n", "{'type': 'shot', 'timestamp': '2022-01-05T11:43:17.030771', 'player': 7, 'points': 3, 'team': 0} \n", "\n", "# Fault\n", "{'type': 'fault', 'timestamp': '2022-01-05T11:43:45.966949', 'player': 6, 'team': 1, 'received_by': 11}]\n", "```\n", "\n", "Design the flow diagram for the main chatbot and the functions required to show the statistics of each player and build a Python program to implement this chatbot" ], "metadata": { "id": "vbwOgs0p-JCD" } }, { "cell_type": "markdown", "source": [ "## Solution\n", "## Flow diagram\n", "In this solution, as suggested in the problem description, we are going to define an array to store the different statistics, collecting the required information from the user when needed. We are going to use two two functions to iterate on the stats array and calculate on the fly the total number of points or the number of faults of the player, so that we can output this information to the user interface. \n", "\n", "The following flow diagram illustrates the diagram flow of the function that calculates the number of points of a player. \n", "\n", "![game statistic points](img/events.png)\n", "\n", "Basically, the function has two input parameters, the player, and the team. Using this data, we iterate over the array and add the points whenever there is a statistic of type point for that player of that team.\n", "\n", "Similarly, the following diagram illustrates the logic of the function that calculates the total faults of a player.\n", "\n", "![game statitisc faults](img/events-get_faults.png)\n", "\n", "Finally, our application is basically a bot that prompts messages in the user interface to get the required data from the user, and appends the statistics to the array, until the user enters the keyword \"stop\" when he/she is prompted for the type of statistic:\n", "\n", "![game statistics](img/events-get_points.png)\n", "\n", "First, our program asks for the name of the game, and the names of the two teams, and for the confirmation of the game start. \n", "Once the game starts, the program initialises the stats_array and starts a while loop where it asks the user for the type of statistic to enter, \n", "either *fault*, *shot*, or *stop* to finalise the game. If the user enters fault, the program asks for the number of the player and the team that made the fault, adds these data to the statistic, and calls the function get_points to show the total number of points. \n", "The logic is similar when there is a shot, we store the player, team, and the number of points, either, 1, 2, or 3. \n", "Finally, if the user enters stop, the program just stops. \n", "\n", "The code below implements this possible solution" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# We will use datetime to represent timestamps\n", "import datetime\n", "\n", "# This is our array of match statistics\n", "stats_array = []\n", "\n", "# Function to get the points of a player\n", "def get_points(player, team):\n", " points = 0\n", " # Iterate on stats and if stat is of type Shot, then count the points\n", " for stat in stats_array:\n", " if stat[\"type\"] == \"shot\" and stat[\"player\"] == player and stat[\"team\"] == team:\n", " points += stat[\"points\"]\n", " \n", " print(\"Player {0} (team {1}) now has {2} points\".format(player_number, teams[team], points))\n", "\n", " return points\n", "\n", "# Function to get the faults of a player\n", "def get_faults(player, team):\n", " faults = 0\n", " #Iterate on stats, and if stat is of type fault and the fault is made by a \n", " #player, then increase the number of faults\n", " for stat in stats_array: \n", " if stat[\"type\"] == \"fault\" and stat[\"player\"] == player and stat[\"team\"] == team:\n", " faults += 1\n", " print(\"Player {0} (team {1}) now has {2} faults\".format(player, teams[team], faults)) \n", " return faults\n", "\n", "# Here we start the script\n", "# Name of the game to be stored in the statistic\n", "game_name = input(\"Enter the name of the game: \")\n", "\n", "# Name of the teams\n", "team_1 = input(\"Enter the name of the first team: \")\n", "team_2 = input(\"Enter the name of the second team: \")\n", "\n", "teams = [team_1, team_2]\n", "#Let´s ask the user for confirmation, we collect the current time and store in the \n", "# stats array a dictionary with the type of stat as game_start and the current date\n", "input(\"Press Enter to confirm game start\")\n", "game_start = datetime.datetime.now()\n", "date_format = \"%X\"\n", "stats_array.append({\"type\": \"game_start\", \"timestamp\": game_start.isoformat(), \"teams\": teams})\n", "print(\"Now: \", game_start)\n", "\n", "\n", "while True:\n", " #Get the stat type from the user\n", " stats_type = input(\"Enter statistic type (either shot or fault), or type stop to end the game: \")\n", " #If the user enter stop, then just break the while loop\n", " if stats_type == \"stop\":\n", " break\n", " else:\n", " # Get the time stamp of the statistic we want to store\n", " stat_date = datetime.datetime.now()\n", " \n", " # store the time stamp and the type of statistic\n", " stat = {\"type\": stats_type, \"timestamp\": stat_date.isoformat()}\n", " \n", " #if it is a shot, get the points and the player\n", " if stats_type == \"shot\":\n", " player_number = int(input(\"Enter the number of the player: \"))\n", " team = int(input(\"Enter player's team (either 0 for {0} or 1 for {1}): \".format(team_1, team_2)))\n", " points = int(input(\"Enter points (either 0 for free shot, 1 for double, 3 for triple): \"))\n", " if (points in [1, 2, 3]) and (team in [0, 1]):\n", " stat[\"player\"]=player_number\n", " stat[\"points\"]=points\n", " stat[\"team\"]=team\n", " stats_array.append(stat)\n", " # Show a message with the total number of points\n", " get_points(player_number, team)\n", " else:\n", " print(\"problem with statistic, try again\")\n", " continue\n", " elif stats_type == \"fault\":\n", " # if it´s a fault, get the player number and the team\n", " player1_number = int(input(\"Enter the number of the player that made the fault: \"))\n", " team = int(input(\"Enter player's team (either 0 for {0} or 1 for {1}): \".format(team_1, team_2)))\n", " if (team in [0, 1]):\n", " #Get the number of the player that received the fault\n", " player2_number = int(input(\"Enter the number of the player that received the fault: \"))\n", " stat[\"player\"]=player1_number\n", " stat[\"team\"]=team\n", " stat[\"received_by\"]=player2_number\n", " stats_array.append(stat)\n", " #Show a message with the number of faults made by player\n", " get_faults(player1_number, team)\n", " else: \n", " print(\"problem with statistic, try again\")\n", " continue\n", "print(stats_array)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": null, "outputs": [], "source": [ "# We will use datetime to represent timestamps\n", "import datetime\n", "\n", "# This is our array of match statistics\n", "stats_array = []\n", "\n", "# Function to get the points of a player\n", "def get_points(player, team):\n", " points = 0\n", " # Iterate on stats and if stat is of type Shot, then count the points\n", " for stat in stats_array:\n", " if stat[\"type\"] == \"shot\" and stat[\"player\"] == player and stat[\"team\"] == team:\n", " points += stat[\"points\"]\n", " \n", " print(\"Player {0} (team {1}) now has {2} points\".format(player_number, teams[team], points))\n", "\n", " return points\n", "\n", "# Function to get the faults of a player\n", "def get_faults(player, team):\n", " faults = 0\n", " #Iterate on stats, and if stat is of type fault and the fault is made by a \n", " #player, then increase the number of faults\n", " for stat in stats_array: \n", " if stat[\"type\"] == \"fault\" and stat[\"player\"] == player and stat[\"team\"] == team:\n", " faults += 1\n", " print(\"Player {0} (team {1}) now has {2} faults\".format(player, teams[team], faults)) \n", " return faults\n", "\n", "# Here we start the script\n", "# Name of the game to be stored in the statistic\n", "game_name = input(\"Enter the name of the game: \")\n", "\n", "# Name of the teams\n", "team_1 = input(\"Enter the name of the first team: \")\n", "team_2 = input(\"Enter the name of the second team: \")\n", "\n", "teams = [team_1, team_2]\n", "#Let´s ask the user for confirmation, we collect the current time and store in the \n", "# stats array a dictionary with the type of stat as game_start and the current date\n", "input(\"Press Enter to confirm game start\")\n", "game_start = datetime.datetime.now()\n", "date_format = \"%X\"\n", "stats_array.append({\"type\": \"game_start\", \"timestamp\": game_start.isoformat(), \"teams\": teams})\n", "print(\"Now: \", game_start)\n", "\n", "\n", "while True:\n", " #Get the stat type from the user\n", " stats_type = input(\"Enter statistic type (either shot or fault), or type stop to end the game: \")\n", " #If the user enter stop, then just break the while loop\n", " if stats_type == \"stop\":\n", " break\n", " else:\n", " # Get the time stamp of the statistic we want to store\n", " stat_date = datetime.datetime.now()\n", " \n", " # store the time stamp and the type of statistic\n", " stat = {\"type\": stats_type, \"timestamp\": stat_date.isoformat()}\n", " \n", " #if it is a shot, get the points and the player\n", " if stats_type == \"shot\":\n", " player_number = int(input(\"Enter the number of the player: \"))\n", " team = int(input(\"Enter player's team (either 0 for {0} or 1 for {1}): \".format(team_1, team_2)))\n", " points = int(input(\"Enter points (either 0 for free shot, 1 for double, 3 for triple): \"))\n", " if (points in [1, 2, 3]) and (team in [0, 1]):\n", " stat[\"player\"]=player_number\n", " stat[\"points\"]=points\n", " stat[\"team\"]=team\n", " stats_array.append(stat)\n", " # Show a message with the total number of points\n", " get_points(player_number, team)\n", " else:\n", " print(\"problem with statistic, try again\")\n", " continue\n", " elif stats_type == \"fault\":\n", " # if it´s a fault, get the player number and the team\n", " player1_number = int(input(\"Enter the number of the player that made the fault: \"))\n", " team = int(input(\"Enter player's team (either 0 for {0} or 1 for {1}): \".format(team_1, team_2)))\n", " if (team in [0, 1]):\n", " #Get the number of the player that received the fault\n", " player2_number = int(input(\"Enter the number of the player that received the fault: \"))\n", " stat[\"player\"]=player1_number\n", " stat[\"team\"]=team\n", " stat[\"received_by\"]=player2_number\n", " stats_array.append(stat)\n", " #Show a message with the number of faults made by player\n", " get_faults(player1_number, team)\n", " else: \n", " print(\"problem with statistic, try again\")\n", " continue\n", "print(stats_array)" ], "metadata": { "collapsed": false } }, { "cell_type": "code", "execution_count": 1, "metadata": { "colab": { "base_uri": "https://localhost:8080/" }, "id": "fjnxZF4xJhZI", "outputId": "e93fd335-bb70-408d-d3f5-b7e6789145e4" }, "outputs": [ { "output_type": "stream", "name": "stdout", "text": [ "Enter the name of the game: ACB game 12\n", "Enter the name of the first team: Valencia Basket\n", "Enter the name of the second team: Real Madrid\n", "Press Enter to confirm game start\n", "Now: 2022-01-05 11:42:03.792167\n", "[{'type': 'game_start', 'timestamp': '2022-01-05T11:42:03.792167', 'teams': ['Valencia Basket', 'Real Madrid']}]\n", "Enter statistic type (either shot or fault), or type stop to end the game: shot\n", "Enter the number of the player: 7\n", "Enter player's team (either 0 for Valencia Basket or 1 for Real Madrid): 0\n", "Enter points (either 0 for free shot, 1 for double, 3 for triple): 3\n", "Player 7 (team Valencia Basket) now has 3 points\n", "Enter statistic type (either shot or fault), or type stop to end the game: fault\n", "Enter the number of the player that made the fault: 6\n", "Enter player's team (either 0 for Valencia Basket or 1 for Real Madrid): 1\n", "Enter the number of the player that received the fault: 11\n", "Player 6 (team Real Madrid) now has 1 faults\n", "Enter statistic type (either shot or fault), or type stop to end the game: stop\n", "[{'type': 'game_start', 'timestamp': '2022-01-05T11:42:03.792167', 'teams': ['Valencia Basket', 'Real Madrid']}, {'type': 'shot', 'timestamp': '2022-01-05T11:43:17.030771', 'player': 7, 'points': 3, 'team': 0}, {'type': 'fault', 'timestamp': '2022-01-05T11:43:45.966949', 'player': 6, 'team': 1, 'received_by': 11}]\n" ] } ], "source": [ "# We will use datetime to represent timestamps\n", "import datetime\n", "\n", "# This is our array of match statistics\n", "stats_array = []\n", "\n", "# Function to get the points of a player\n", "def get_points(player, team):\n", " points = 0\n", " # Iterate on stats and if stat is of type Shot, then count the points\n", " for stat in stats_array:\n", " if stat[\"type\"] == \"shot\" and stat[\"player\"] == player and stat[\"team\"] == team:\n", " points += stat[\"points\"]\n", " \n", " print(\"Player {0} (team {1}) now has {2} points\".format(player_number, teams[team], points))\n", "\n", " return points\n", "\n", "# Function to get the faults of a player\n", "def get_faults(player, team):\n", " faults = 0\n", " #Iterate on stats, and if stat is of type fault and the fault is made by a \n", " #player, then increase the number of faults\n", " for stat in stats_array: \n", " if stat[\"type\"] == \"fault\" and stat[\"player\"] == player and stat[\"team\"] == team:\n", " faults += 1\n", " print(\"Player {0} (team {1}) now has {2} faults\".format(player, teams[team], faults)) \n", " return faults\n", "\n", "# Here we start the script\n", "# Name of the game to be stored in the statistic\n", "game_name = input(\"Enter the name of the game: \")\n", "\n", "# Name of the teams\n", "team_1 = input(\"Enter the name of the first team: \")\n", "team_2 = input(\"Enter the name of the second team: \")\n", "\n", "teams = [team_1, team_2]\n", "#Let´s ask the user for confirmation, we collect the current time and store in the \n", "# stats array a dictionary with the type of stat as game_start and the current date\n", "input(\"Press Enter to confirm game start\")\n", "game_start = datetime.datetime.now()\n", "date_format = \"%X\"\n", "stats_array.append({\"type\": \"game_start\", \"timestamp\": game_start.isoformat(), \"teams\": teams})\n", "print(\"Now: \", game_start)\n", "\n", "\n", "while True:\n", " #Get the stat type from the user\n", " stats_type = input(\"Enter statistic type (either shot or fault), or type stop to end the game: \")\n", " #If the user enter stop, then just break the while loop\n", " if stats_type == \"stop\":\n", " break\n", " else:\n", " # Get the time stamp of the statistic we want to store\n", " stat_date = datetime.datetime.now()\n", " \n", " # store the time stamp and the type of statistic\n", " stat = {\"type\": stats_type, \"timestamp\": stat_date.isoformat()}\n", " \n", " #if it is a shot, get the points and the player\n", " if stats_type == \"shot\":\n", " player_number = int(input(\"Enter the number of the player: \"))\n", " team = int(input(\"Enter player's team (either 0 for {0} or 1 for {1}): \".format(team_1, team_2)))\n", " points = int(input(\"Enter points (either 0 for free shot, 1 for double, 3 for triple): \"))\n", " if (points in [1, 2, 3]) and (team in [0, 1]):\n", " stat[\"player\"]=player_number\n", " stat[\"points\"]=points\n", " stat[\"team\"]=team\n", " stats_array.append(stat)\n", " # Show a message with the total number of points\n", " get_points(player_number, team)\n", " else:\n", " print(\"problem with statistic, try again\")\n", " continue\n", " elif stats_type == \"fault\":\n", " # if it´s a fault, get the player number and the team\n", " player1_number = int(input(\"Enter the number of the player that made the fault: \"))\n", " team = int(input(\"Enter player's team (either 0 for {0} or 1 for {1}): \".format(team_1, team_2)))\n", " if (team in [0, 1]):\n", " #Get the number of the player that received the fault\n", " player2_number = int(input(\"Enter the number of the player that received the fault: \"))\n", " stat[\"player\"]=player1_number\n", " stat[\"team\"]=team\n", " stat[\"received_by\"]=player2_number\n", " stats_array.append(stat)\n", " #Show a message with the number of faults made by player\n", " get_faults(player1_number, team)\n", " else: \n", " print(\"problem with statistic, try again\")\n", " continue\n", "print(stats_array)" ] } ] }